package org.hs.phd.odi.tracking.tracker.testbeds;

import java.awt.Color;
import java.awt.GradientPaint;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.Paint;
import java.awt.Polygon;
import java.awt.Rectangle;
import java.awt.image.BufferedImage;
import java.util.ArrayList;
import java.util.List;

import javax.swing.ImageIcon;

import org.hs.phd.odi.tracking.tracker.TrackerUtils;
import org.hs.phd.odi.tracking.tracker.util.TestUtils;

import com.googlecode.javacv.cpp.opencv_core;
import com.googlecode.javacv.cpp.opencv_core.IplImage;

public class FixedSizedFixedRotationBlueRectangleOverWhiteBackgroundTestBed {
	

	static class ListTestSequence implements TrackerTestSequence{
		
		private final List<IplImage> frames;
		private final List<Polygon> trackShapes;
		private final String name;

		public ListTestSequence(String name) {
			this.name = name;
			this.frames = new ArrayList<opencv_core.IplImage>();
			this.trackShapes = new ArrayList<Polygon>();
		}
		
		void addFrame(IplImage frame, Polygon trackShape){
			frames.add(frame);
			trackShapes.add(trackShape);
		}

		@Override
		public IplImage getFrame(int index) {
			return frames.get(index);
		}

		@Override
		public Polygon getTrackShape(int index) {
			return trackShapes.get(index);
		}

		@Override
		public int getFrameCount() {
			return frames.size();
		}

		@Override
		public String getName() {
			return name;
		}
		
	}
	
	static class SyntheticTestSequence extends ListTestSequence{

		private static final int SYNTHETIC_SEQUENCE_FRAME_WIDTH = 200;
		private static final int SYNTHETIC_SEQUENCE_FRAME_HEIGHT = 300;
		private static final int SYNTHETIC_SEQUENCE_TRACK_RECT_WIDTH = 40;
		private static final int SYNTHETIC_SEQUENCE_TRACK_RECT_HEIGHT = 50;
		private final int syntheticSequenceFrameWidth;
		private final int syntheticSequenceFrameHeight;
		private final int syntheticSequenceTrackRectWidth;
		private final int syntheticSequenceTrackRectHeight;
		private final Paint bgPaint;
		private final Paint rectPaint;

		public SyntheticTestSequence(String name) {
			this(name, SYNTHETIC_SEQUENCE_FRAME_WIDTH, SYNTHETIC_SEQUENCE_FRAME_HEIGHT, SYNTHETIC_SEQUENCE_TRACK_RECT_WIDTH, SYNTHETIC_SEQUENCE_TRACK_RECT_HEIGHT );
		}
		
		public SyntheticTestSequence(String name, int syntheticSequenceFrameWidth, int syntheticSequenceFrameHeight, int syntheticSequenceTrackRectWidth, int syntheticSequenceTrackRectHeight) {
			this(name, Color.WHITE, Color.BLUE, SYNTHETIC_SEQUENCE_FRAME_WIDTH, SYNTHETIC_SEQUENCE_FRAME_HEIGHT, SYNTHETIC_SEQUENCE_TRACK_RECT_WIDTH, SYNTHETIC_SEQUENCE_TRACK_RECT_HEIGHT );
		}
		
		public SyntheticTestSequence(String name, Paint bgPaint, Paint rectPaint, int syntheticSequenceFrameWidth, int syntheticSequenceFrameHeight, int syntheticSequenceTrackRectWidth, int syntheticSequenceTrackRectHeight) {
			super(name);
			this.bgPaint = bgPaint;
			this.rectPaint = rectPaint;
			this.syntheticSequenceFrameWidth = syntheticSequenceFrameWidth;
			this.syntheticSequenceFrameHeight = syntheticSequenceFrameHeight;
			this.syntheticSequenceTrackRectWidth = syntheticSequenceTrackRectWidth;
			this.syntheticSequenceTrackRectHeight = syntheticSequenceTrackRectHeight;
		}

		public void addSyntheticFrame(int trackRectX, int trackRectY) {
			Rectangle trackRect = new Rectangle( trackRectX, trackRectY, 
					syntheticSequenceTrackRectWidth, syntheticSequenceTrackRectHeight);

			IplImage iplImage = TestUtils.getRectangleImage( syntheticSequenceFrameWidth,
					syntheticSequenceFrameHeight, 
					trackRectX, trackRectY, syntheticSequenceTrackRectWidth, syntheticSequenceTrackRectHeight,
					bgPaint, rectPaint);
			addFrame(iplImage, TrackerUtils.getAsPolygon(trackRect) );
		}
		
	}
	
	
	private static IplImage loadOpenCVImageFromResource(String resource) {
		Image image = new ImageIcon(FixedSizedFixedRotationBlueRectangleOverWhiteBackgroundTestBed.class.getResource(resource)).getImage();
		BufferedImage bufferedImage = new BufferedImage(image.getWidth(null),
				image.getHeight(null), BufferedImage.TYPE_3BYTE_BGR );
		Graphics g = bufferedImage.getGraphics();
		g.drawImage(image, 0, 0, null);
		g.dispose();
		IplImage iplImage = IplImage.createFrom(bufferedImage);
		return iplImage;
	}

	public static TrackerTestSequence createStationaryObjectSequence() {
		SyntheticTestSequence testSequence = new SyntheticTestSequence("StationaryObjectSequence");

		for(int i = 0; i < 3; i++){
			testSequence.addSyntheticFrame(10, 10);
		}
		
		return testSequence;
	}

	public static TrackerTestSequence createLeftToRightSequence() {
		SyntheticTestSequence testSequence = new SyntheticTestSequence("LeftToRightSequence");
		
		int x = 10;
		int y = 10;
		
		for(int i = 0; i < 10; i++){
			testSequence.addSyntheticFrame(x, y);
			x += 3;
		}

		return testSequence;
	}

	public static TrackerTestSequence createLeftToRightSequenceVerySlow() {
		SyntheticTestSequence testSequence = new SyntheticTestSequence("LeftToRightSequenceVerySlow");
		
		float x = 10;
		float y = 10;
		
		for(int i = 0; i < 100; i++){
			testSequence.addSyntheticFrame((int)x, (int)y);
			x += 0.3;
		}

		return testSequence;
	}

	public static TrackerTestSequence createRightToLeftSequence() {
		SyntheticTestSequence testSequence = new SyntheticTestSequence("RightToLeftSequence");
		
		int x = 140;
		int y = 10;
		
		for(int i = 0; i < 10; i++){
			testSequence.addSyntheticFrame(x, y);
			x -= 3;
		}

		return testSequence;
	}

	public static TrackerTestSequence createTopToBottomSequence() {
		SyntheticTestSequence testSequence = new SyntheticTestSequence("TopToBottomSequence");
		
		int x = 10;
		int y = 3;
		
		for(int i = 0; i < 10; i++){
			testSequence.addSyntheticFrame(x, y);
			y += 3;
		}

		return testSequence;
	}

	public static TrackerTestSequence createBottomToTopSequence() {
		SyntheticTestSequence testSequence = new SyntheticTestSequence("BottomToTopSequence");
		
		int x = 10;
		int y = 140;
		
		for(int i = 0; i < 10; i++){
			testSequence.addSyntheticFrame(x, y);
			y -= 3;
		}

		return testSequence;
	}

	public static TrackerTestSequence createArbitraryTranslationSequence() {
		SyntheticTestSequence testSequence = new SyntheticTestSequence("ArbitraryTranslationSequence");
		
		testSequence.addSyntheticFrame(10, 10);
		testSequence.addSyntheticFrame(13, 10);
		testSequence.addSyntheticFrame(13, 13);
		testSequence.addSyntheticFrame(10, 10);
		testSequence.addSyntheticFrame(13, 13);
		testSequence.addSyntheticFrame(18, 22);
		testSequence.addSyntheticFrame(19, 27);
		testSequence.addSyntheticFrame(14, 35);

		return testSequence;
	}

	public static TrackerTestSequence createArbitraryTranslationSequence2() {
		SyntheticTestSequence testSequence = new SyntheticTestSequence("ArbitraryTranslationSequence2",
				400, 400,
				69, 99);
		
		testSequence.addSyntheticFrame(151, 141);
		testSequence.addSyntheticFrame(130, 151);
		testSequence.addSyntheticFrame(151, 141);
		testSequence.addSyntheticFrame(130, 151);
		testSequence.addSyntheticFrame(151, 141);
		testSequence.addSyntheticFrame(130, 151);
		testSequence.addSyntheticFrame(151, 141);
		testSequence.addSyntheticFrame(130, 151);
		return testSequence;
	}

	public static TrackerTestSequence createPNGSequence() {
		ListTestSequence testSequence = new ListTestSequence("PNGTestSequence");
		
		testSequence.addFrame(loadOpenCVImageFromResource( "blueRectOverWhiteBgImages/frame0.png" ), 
				TrackerUtils.getAsPolygon(new Rectangle(151, 141, 69, 99)) );
		testSequence.addFrame(loadOpenCVImageFromResource( "blueRectOverWhiteBgImages/frame0.png" ), 
				TrackerUtils.getAsPolygon(new Rectangle(151, 141, 69, 99)) );
		testSequence.addFrame(loadOpenCVImageFromResource( "blueRectOverWhiteBgImages/frame1.png" ), 
				TrackerUtils.getAsPolygon(new Rectangle(130, 151, 69, 99)) );
		
		return testSequence;
	}

	public static TrackerTestSequence createColorfullTranslationSequence() {
		Paint bgPaint = new GradientPaint(10, 10, Color.YELLOW, 200, 200, Color.RED);
		
		Paint rectPaint = new GradientPaint(10, 10, Color.BLUE, 50, 30, Color.GREEN);
		
		
		SyntheticTestSequence testSequence = new SyntheticTestSequence("ColorfullTranslationSequence",
				bgPaint, rectPaint, SyntheticTestSequence.SYNTHETIC_SEQUENCE_FRAME_WIDTH, SyntheticTestSequence.SYNTHETIC_SEQUENCE_FRAME_HEIGHT, 
				SyntheticTestSequence.SYNTHETIC_SEQUENCE_TRACK_RECT_WIDTH, SyntheticTestSequence.SYNTHETIC_SEQUENCE_TRACK_RECT_HEIGHT);
		
		int x = 10;
		int y = 10;
		
		for(int i = 0; i < 40; i++){
			testSequence.addSyntheticFrame(x, y);
			x += 3;
		}

		return testSequence;
	}

	
	public static TrackerTestSequence createColorfullTranslationSequence2() {
		Paint bgPaint = new GradientPaint(10, 10, Color.RED, 200, 200, Color.BLUE);
		
		Paint rectPaint = new GradientPaint(10, 10, Color.BLUE, 50, 30, Color.GREEN);
		
		
		SyntheticTestSequence testSequence = new SyntheticTestSequence("ColorfullTranslationSequence",
				bgPaint, rectPaint, 400, 400, 
				SyntheticTestSequence.SYNTHETIC_SEQUENCE_TRACK_RECT_WIDTH, SyntheticTestSequence.SYNTHETIC_SEQUENCE_TRACK_RECT_HEIGHT);
		
		int x = 10;
		int y = 10;
		
		for(int i = 0; i < 6; i++){
			testSequence.addSyntheticFrame(x, y);
			x += 25;
			y += 25;
		}

		return testSequence;
	}

	
	

}
